<!DOCTYPE html>
<html lang="en">
<head>
    
    <meta charset="utf-8">
    <title>utils.js - Aliwork helper</title>
    
    <meta name="description" content="宜搭前端 JS 工具代码库" />
    
        <meta name="keywords" content="Aliwork 宜搭 工具库" />
        <meta name="keyword" content="Aliwork 宜搭 工具库" />
    
    
    
    <script src="scripts/prettify/prettify.js"></script>
    <script src="scripts/prettify/lang-css.js"></script>
    <!--[if lt IE 9]>
      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
    <link type="text/css" rel="stylesheet" href="styles/prettify.css">
    <link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
    <script src="scripts/nav.js" defer></script>
    
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>

<input type="checkbox" id="nav-trigger" class="nav-trigger" />
<label for="nav-trigger" class="navicon-button x">
  <div class="navicon"></div>
</label>

<label for="nav-trigger" class="overlay"></label>

<nav >
    
    <input type="text" id="nav-search" placeholder="Search" />
    
    
    <h2><a href="index.html">Home</a></h2><h2><a href="https://github.com/hackingzhang/aliwork-helper" target="_blank" class="menu-item" >Github</a></h2><h2><a href="https://gitee.com/hexzhangshuai/aliwork-helper" target="_blank" class="menu-item" >Gitee码云</a></h2><h2><a href="https://docs.aliwork.com/docs/developer/api/about" target="_blank" class="menu-item" >宜搭开放API</a></h2><h3>Modules</h3><ul><li><a href="module-DataLinkage.html">DataLinkage</a><ul class='methods'><li data-type='method'><a href="module-DataLinkage.html#.dataLinkage">dataLinkage</a></li><li data-type='method'><a href="module-DataLinkage.html#.dataLinkageSubform">dataLinkageSubform</a></li><li data-type='method'><a href="module-DataLinkage.html#~resolveConditionMap">resolveConditionMap</a></li></ul></li><li><a href="module-DataSource.html">DataSource</a><ul class='methods'><li data-type='method'><a href="module-DataSource.html#.deleteFormData">deleteFormData</a></li><li data-type='method'><a href="module-DataSource.html#.executeTask">executeTask</a></li><li data-type='method'><a href="module-DataSource.html#.fetchSubformDatas">fetchSubformDatas</a></li><li data-type='method'><a href="module-DataSource.html#.fetchSubformDatasAll">fetchSubformDatasAll</a></li><li data-type='method'><a href="module-DataSource.html#.getFormData">getFormData</a></li><li data-type='method'><a href="module-DataSource.html#.getOperationRecords">getOperationRecords</a></li><li data-type='method'><a href="module-DataSource.html#.saveFormData">saveFormData</a></li><li data-type='method'><a href="module-DataSource.html#.searchFormDataIds">searchFormDataIds</a></li><li data-type='method'><a href="module-DataSource.html#.searchFormDataIdsAll">searchFormDataIdsAll</a></li><li data-type='method'><a href="module-DataSource.html#.searchFormDatas">searchFormDatas</a></li><li data-type='method'><a href="module-DataSource.html#.searchFormDatasAll">searchFormDatasAll</a></li><li data-type='method'><a href="module-DataSource.html#.startInstance">startInstance</a></li><li data-type='method'><a href="module-DataSource.html#.updateFormData">updateFormData</a></li></ul></li><li><a href="module-Field.html">Field</a><ul class='methods'><li data-type='method'><a href="module-Field.html#.activateTabItems">activateTabItems</a></li><li data-type='method'><a href="module-Field.html#.fieldToString">fieldToString</a></li><li data-type='method'><a href="module-Field.html#.fieldValueDiff">fieldValueDiff</a></li><li data-type='method'><a href="module-Field.html#.fieldValueEqualSingle">fieldValueEqualSingle</a></li><li data-type='method'><a href="module-Field.html#.generateAssociationFormFieldData">generateAssociationFormFieldData</a></li><li data-type='method'><a href="module-Field.html#.generateDptFieldData">generateDptFieldData</a></li><li data-type='method'><a href="module-Field.html#.generateEmployeeFieldData">generateEmployeeFieldData</a></li><li data-type='method'><a href="module-Field.html#.getFieldDataTypeById">getFieldDataTypeById</a></li><li data-type='method'><a href="module-Field.html#.getFieldTypeById">getFieldTypeById</a></li><li data-type='method'><a href="module-Field.html#.mergeTo">mergeTo</a></li><li data-type='method'><a href="module-Field.html#.syncTo">syncTo</a></li></ul></li><li><a href="module-Subform.html">Subform</a><ul class='methods'><li data-type='method'><a href="module-Subform.html#.associateForm2Subform">associateForm2Subform</a></li><li data-type='method'><a href="module-Subform.html#.sum2Main">sum2Main</a></li><li data-type='method'><a href="module-Subform.html#~resolveFieldMaps">resolveFieldMaps</a></li></ul></li><li><a href="module-UI.html">UI</a><ul class='methods'><li data-type='method'><a href="module-UI.html#.dialog">dialog</a></li><li data-type='method'><a href="module-UI.html#.hijackSubmit">hijackSubmit</a></li><li data-type='method'><a href="module-UI.html#.loading">loading</a></li></ul></li><li><a href="module-Utils.html">Utils</a><ul class='methods'><li data-type='method'><a href="module-Utils.html#.dateTimeFormat">dateTimeFormat</a></li><li data-type='method'><a href="module-Utils.html#.generateRandomId">generateRandomId</a></li><li data-type='method'><a href="module-Utils.html#.isEmpty">isEmpty</a></li><li data-type='method'><a href="module-Utils.html#.retry">retry</a></li><li data-type='method'><a href="module-Utils.html#.round">round</a></li><li data-type='method'><a href="module-Utils.html#.sleep">sleep</a></li></ul></li></ul><h3>Classes</h3><ul><li><a href="FieldChangeLogger.html">FieldChangeLogger</a><ul class='methods'><li data-type='method'><a href="FieldChangeLogger.html#change">change</a></li><li data-type='method'><a href="FieldChangeLogger.html#clear">clear</a></li><li data-type='method'><a href="FieldChangeLogger.html#format">format</a></li></ul></li><li><a href="module-Subform-Subform.html">Subform</a><ul class='methods'><li data-type='method'><a href="module-Subform-Subform.html#getDatas">getDatas</a></li><li data-type='method'><a href="module-Subform-Subform.html#getFormGroupId">getFormGroupId</a></li><li data-type='method'><a href="module-Subform-Subform.html#getFormGroupIds">getFormGroupIds</a></li><li data-type='method'><a href="module-Subform-Subform.html#getIndex">getIndex</a></li><li data-type='method'><a href="module-Subform-Subform.html#getInstance">getInstance</a></li><li data-type='method'><a href="module-Subform-Subform.html#getItem">getItem</a></li><li data-type='method'><a href="module-Subform-Subform.html#setDatas">setDatas</a></li><li data-type='method'><a href="module-Subform-Subform.html#summary">summary</a></li><li data-type='method'><a href="module-Subform-Subform.html#updateItem">updateItem</a></li></ul></li></ul>
    
</nav>

<div id="main">
    
    <h1 class="page-title">utils.js</h1>
    

    



    
    <section>
        <article>
            <pre class="prettyprint source linenums"><code>/**
 * 一些辅助工具方法
 * @module Utils
 */

/**
 * sleep函数，可在异步场景中实现延时或者暂停执行
 * @static
 * @param {number} time sleep时间，单位毫秒
 * @returns {Promise} 一个Promise，在time毫秒后被resolve
 *
 * @example
 * async function batchUpdate(datas) {
 *   // 批量调用接口更新数据，每次更新之间等待1秒钟以防止频繁请求导致接口被限制
 *   for (const data of datas) {
 *     await doUpdate(data);
 *     await sleep(1000);
 *   }
 * }
 */
function sleep(time) {
  return new Promise((resolve) => {
    setTimeout(resolve, time);
  });
}

/**
 * 函数失败重试 &lt;br/>
 * @static
 * @param {Function} callable 要执行的函数。如果函数抛出异常则进行重试，
 * 支持函数返回Promise，如果返回的Promise被reject则进行重试
 * @param {number} retryTimes 重试次数
 * @param {number} retryDelay 重试延时，单位毫秒，默认300ms
 * @param {...*} args 传递给callable的参数
 *
 * @example
 * async function updateFormData(formData) {
 *   const resp = await doUpdate(formData);
 *   if (resp.error) {
 *     throw Error(resp.error);
 *   }
 * }
 *
 * export async function onClick() {
 *   // 当updateFormData失败时，等待500毫秒再次调用updateFormData，最多重试5次
 *   retrey(() => updateFormData(), 5, 500, { field_123: "value" })
 * }
 */
async function retry(callable, retryTimes = 3, retryDelay = 300, ...args) {
  let times = 0;
  let result;
  let error;
  while (times &lt;= retryTimes) {
    if (times > 0) {
      await sleep(retryDelay);
    }
    try {
      result = callable(...args);
      if (result instanceof Promise) {
        await result;
      }
      return result;
    } catch (e) {
      times += 1;
      error = e;
    }
  }

  let errorMsg = `All ${retryTimes} retries failed.`;
  if (error) errorMsg += `Error: ${error.message}`;
  throw Error(errorMsg);
}

/**
 * 判断一个值是否为空 &lt;br/>
 * 这些情况会被判定为空：空字符串、null、undefined、NaN、空数组、空对象、空Map、空Set
 * @static
 * @param {any} value - 任意值
 * @returns {boolean} - 值是否为空
 *
 * @example
 * isEmpty(""); // true
 * isEmpty([]); // true
 * isEmpty(undefined); // true
 * isEmpty(null); // true
 * isEmpty(NaN); // true
 * isEmpty({}); // true
 * isEmpty(new Map()); // true
 * isEmpty(new Set()); // true
 *
 * isEmpty(0); // false
 * isEmpty({a: 1}); // false
 * isEmpty(new Map().set("a", "1")); // false
 */
function isEmpty(value) {
  if (
    value === "" ||
    value === null ||
    value === undefined ||
    (typeof value === "number" &amp;&amp; isNaN(value))
  )
    return true;

  if (typeof value === "object") {
    if (Array.isArray(value)) return value.length === 0;
    if (value instanceof Map) return value.size === 0;
    if (value instanceof Set) return value.size === 0;
    if (value instanceof WeakMap) return false;
    if (value instanceof WeakSet) return false;

    // 普通对象
    if (Object.keys(value).length === 0) return true;
  }

  return false;
}

/**
 * 日期格式化
 * @static
 * @param {Date} dateTime Date对象
 * @param {string} format 格式化字符串，遵循ISO8601标准(YYYYY-MM-DDTHH:mm:ss.sssZ)
 *
 * @example
 * dateTimeFormat(new Date(1704067200000), "YYYY年MM月DD日"); // 2024年01月01日
 * dateTimeFormat(new Date(1704067200000), "HH时mm分ss秒sss"); // 08时00分00秒000
 * dateTimeFormat(new Date(1704067200000), "YYYY年MM月DD日 HH时mm分ss秒sss"); // 2024年01月01日 08时00分00秒000
 */
function dateTimeFormat(dateTime, format) {
  if (!dateTime) {
    dateTime = new Date();
  }

  function padStart(str, maxLen = 2) {
    if (typeof str !== "string") {
      str = String(str);
    }
    return str.padStart(maxLen, "0");
  }

  var year = padStart(dateTime.getFullYear(), 4);
  var month = padStart(dateTime.getMonth() + 1);
  var date = padStart(dateTime.getDate());
  var hours = padStart(dateTime.getHours());
  var minutes = padStart(dateTime.getMinutes());
  var seconds = padStart(dateTime.getSeconds());
  var milliseconds = padStart(dateTime.getMilliseconds(), 3);

  var replacement = [
    { key: "YYYY", value: year },
    { key: "MM", value: month },
    { key: "DD", value: date },
    { key: "HH", value: hours },
    { key: "mm", value: minutes },
    { key: "sss", value: milliseconds },
    { key: "ss", value: seconds },
  ];

  for (var item of replacement) {
    format = format.replace(item.key, item.value);
  }

  return format;
}

/**
 * 生成一个（伪）随机ID
 * @static
 * @param {number} length ID长度
 * @returns {string} 生成的ID
 *
 * @example
 * const id = generateRandomId(); // 生成一个32个字符的ID
 * const id = generateRandomId(16); // 生成一个16个字符的ID
 */
function generateRandomId(length = 32) {
  const validChars = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  let id = "";
  for (let i = 0; i &lt; length; i++) {
    id += validChars[Math.floor(Math.random() * 35)];
  }

  return id;
}

/**
 * 四舍五入
 * @static
 * @param {number} number 数字
 * @param {number} digits 要保留的小数位数
 * @returns {number} 四舍五入后的数字
 *
 * @example
 * 0.1 + 0.2; // 0.30000000000000004
 * round(0.1 + 0.2); // 0.3
 * 
 * 0.123 * 3.4; // 0.41819999999999996
 * round(0.123 * 3.4); // 0.42
 * round(0.123 * 3.4, 3); // 0.418
 */
function round(number, digits = 2) {
  const magic = Math.pow(10, digits);
  return Math.round(number * magic) / magic;
}

export { sleep, retry, isEmpty, dateTimeFormat, generateRandomId, round };
</code></pre>
        </article>
    </section>




    
    
</div>

<br class="clear">

<footer>
    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.2</a> on Tue Mar 19 2024 17:01:50 GMT+0800 (中国标准时间) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
</footer>

<script>prettyPrint();</script>
<script src="scripts/polyfill.js"></script>
<script src="scripts/linenumber.js"></script>

<script src="scripts/search.js" defer></script>



</body>
</html>
